package com.noah2021.controller;

import com.noah2021.dao.ItemDOMapper;
import com.noah2021.dao.ItemStockDOMapper;
import com.noah2021.dao.PromoDOMapper;
import com.noah2021.error.BusinessException;
import com.noah2021.error.EmBusinessError;
import com.noah2021.pojo.ItemDO;
import com.noah2021.pojo.ItemStockDO;
import com.noah2021.pojo.PromoDO;
import com.noah2021.response.CommonReturnType;
import com.noah2021.service.CacheService;
import com.noah2021.service.ItemService;
import com.noah2021.service.PromoService;
import com.noah2021.service.model.ItemModel;
import com.noah2021.controller.viewobject.ItemVO;
import com.noah2021.util.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.joda.time.Minutes;
import org.joda.time.format.DateTimeFormat;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 〈〉
 *
 * @author Noah2021
 * @create 2021/2/7
 * @return
 */
@Controller
@RequestMapping("/item")
@CrossOrigin(allowCredentials = "true", allowedHeaders = "*")
@Slf4j
public class ItemController extends BaseController {
    @Autowired
    ItemService itemService;

    @Autowired
    CacheService cacheService;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private PromoService promoService;

    @RequestMapping(value = "/create", method = {RequestMethod.POST}, consumes = {CONTENT_TYPE_FORMED})
    @ResponseBody
    public CommonReturnType createItem(@RequestParam(name = "title") String title,
                                       @RequestParam(name = "description") String description,
                                       @RequestParam(name = "price") BigDecimal price,
                                       @RequestParam(name = "stock") Integer stock,
                                       @RequestParam(name = "imgUrl") String imgUrl) throws BusinessException {

        //封装service请求用来创建商品
        ItemModel itemModel = new ItemModel();
        itemModel.setTitle(title);
        itemModel.setDescription(description);
        itemModel.setPrice(price);
        itemModel.setStock(stock);
        itemModel.setImgUrl(imgUrl);
        ItemModel model = itemService.createItem(itemModel);
        ItemVO itemVO = this.convertFromItemModel(model);
        return CommonReturnType.create(itemVO);
    }


    /**
     * 商品详情页浏览
     * 获得一个也需要缓存吗，而且他为什么不一致了。。，感觉一个列表缓存一下差不多，因为太多了
     * 一个东西的话 从数据库拿 是不是也很快呢。。不过是不是因为他要逛淘宝 会点进去很多的商品
     * 所以要缓存，但是一个人不会点进去一个 然后等会又点进去这个吧，虽然如果有很多人的话
     * 确实有些商品会被点进去很多次
     * 用的缓存不对啊 管理端没必要缓存吧
     * @param id
     * @return
     * @throws BusinessException
     */
    @RequestMapping("/get")
    @ResponseBody
    public CommonReturnType getItem(@RequestParam("id") Integer id) throws BusinessException {
//        ItemModel itemModel = itemService.getItemById(id);
        ItemModel itemModel = null;
        //取本地缓存
        itemModel = (ItemModel) cacheService.getFromCommonCache("item_" + id);
        log.info("取得本地缓存 {}",itemModel);
        if(itemModel == null){
            //从redis中取
            itemModel = (ItemModel) redisTemplate.opsForValue().get("item_" + id);
            log.info("取得redis 缓存 {}",itemModel);
            if (itemModel == null) {
                //从mysql中取
                itemModel = itemService.getItemById(id);
                log.info("取得mysql数据，存入redis 和本地缓存 {}",itemModel);
//                这缓存有问题啊
//                因为mq 也要用到缓存 所以 前端请求需要用这个接口
                redisTemplate.opsForValue().set("item_" + id, itemModel);
                redisTemplate.expire("item_" + id, 10, TimeUnit.MINUTES);
            }
            cacheService.setCommonCache("item_"+id, itemModel);
        }
//            throw new BusinessException(EmBusinessError.STOCK_NOT_ENOUGH, "该商品不存在");
        ItemVO itemVO = convertFromItemModel(itemModel);
        return CommonReturnType.create(itemVO);
    }

    @RequestMapping("/refresh")
    @ResponseBody
    public CommonReturnType refresh(@RequestParam("id") Integer id) throws BusinessException {
//        ItemModel itemModel = itemService.getItemById(id);
        ItemModel itemModel = null;
        //取本地缓存
//        itemModel = (ItemModel) cacheService.getFromCommonCache("item_" + id);
//        cacheService.setCommonCache();
        itemModel = itemService.getItemById(id);
        String itemKey = RedisUtil.getItemKey(id);
        redisTemplate.opsForValue().set(itemKey, itemModel);
        redisTemplate.expire(itemKey, 10, TimeUnit.MINUTES);
        cacheService.setCommonCache(itemKey, itemModel);

//            throw new BusinessException(EmBusinessError.STOCK_NOT_ENOUGH, "该商品不存在");
        ItemVO itemVO = convertFromItemModel(itemModel);
        return CommonReturnType.create(itemVO);
    }

    @Autowired
    ItemStockDOMapper itemStockDOMapper;
    @RequestMapping("/mysql/get")
    @ResponseBody
    public CommonReturnType mysqlGet(@RequestParam("id") Integer id) throws BusinessException {
//        ItemModel itemModel = itemService.getItemById(id);
        ItemModel itemModel = null;
        //取本地缓存
//        itemModel = (ItemModel) cacheService.getFromCommonCache("item_" + id);
//        cacheService.setCommonCache();
        itemModel = itemService.getItemById(id);
//        这里的sales 是正确的吗
//        itemService。
//        item
        ItemStockDO itemStockDO = itemStockDOMapper.selectByItemId(id);
        log.info("itemStockDO {}",itemStockDO);
        itemModel.setStock(itemStockDO.getStock());
//        String itemKey = RedisUtil.getItemKey(id);
//        redisTemplate.opsForValue().set(itemKey, itemModel);
//        redisTemplate.expire(itemKey, 10, TimeUnit.MINUTES);
//        cacheService.setCommonCache(itemKey, itemModel);

//            throw new BusinessException(EmBusinessError.STOCK_NOT_ENOUGH, "该商品不存在");
        ItemVO itemVO = convertFromItemModel(itemModel);
        return CommonReturnType.create(itemVO);
    }

    @Autowired
    PromoDOMapper promoDOMapper;
    /**
     *
     * @param promoId 促销id 而不是 商品的id
     * @return
     */
    @RequestMapping(value = "/publishpromo",method = {RequestMethod.GET})
    @ResponseBody
    public CommonReturnType publishPromo(@RequestParam(name = "id")Integer promoId){
//        promoService.publishPromo(promoId);
//        return CommonReturnType.create(null);

        PromoDO promoDO = promoDOMapper.selectByPrimaryKey(promoId);
        if(promoDO==null){
            return  CommonReturnType.fail("没有这个促销");
        }
        if (promoDO.getItemId() == null || promoDO.getItemId().intValue() == 0){
            return  CommonReturnType.fail("没有这个促销");
        }
//            return;
        ItemModel itemModel = itemService.getItemById(promoDO.getItemId());
        redisTemplate.opsForValue().set("promo_item_stock_" + itemModel.getId(),
                itemModel.getStock());
        //将大闸限制的数字设到redis内
        redisTemplate.opsForValue().set("promo_door_count_"+promoId, itemModel.getStock().intValue()*5);
      return  CommonReturnType.create("成功");
    }

    @RequestMapping(value = "/getItemStock",method = {RequestMethod.GET})
    @ResponseBody
    public CommonReturnType getItemStock(@RequestParam(name = "itemId")Integer itemId){
//        promoService.publishPromo(itemId);
        String itemStockKey = RedisUtil.getItemStockKey(itemId);
//    int  itemStock= (int) redisTemplate.opsForValue().get(itemStockKey);
//        java.lang.NullPointerException
        Integer  itemStock= (Integer) redisTemplate.opsForValue().get(itemStockKey);
        if(itemStock==null){
            return CommonReturnType.create("没有发布活动",CommonReturnType.fail);
        }
        return CommonReturnType.create(itemStock);
    }

    @Autowired
    ItemDOMapper itemDOMapper;

    /**
     * 都没有 stock 字段啊
     * @param itemVO
     * @return
     */
    @RequestMapping(value = "/update",method = {RequestMethod.POST})
    @ResponseBody
    public CommonReturnType update(@RequestBody ItemVO itemVO){
//        promoService.publishPromo(itemId);
//        itemDO.ge
//        ItemVO
//        itemVO.ge
//        itemService.se
//        itemStockDOMapper.
//        item


        ItemDO itemDO = itemVO.toItemDO();
        log.info("itemVO {}",itemVO);
        int i = itemDOMapper.updateByPrimaryKeySelective(itemDO);
//        String itemStockKey = RedisUtil.getItemStockKey(itemId);
////    int  itemStock= (int) redisTemplate.opsForValue().get(itemStockKey);
////        java.lang.NullPointerException
//        Integer  itemStock= (Integer) redisTemplate.opsForValue().get(itemStockKey);
//        if(itemStock==null){
//            return CommonReturnType.create("没有发布活动",CommonReturnType.fail);
//        }
        return CommonReturnType.create("成功");
    }



    /**
     * 商品列表页面浏览 会显示他的秒杀活动
     * @return
     */
    @RequestMapping(value = "/list", method = {RequestMethod.GET})
    @ResponseBody
    public CommonReturnType listItem() {
        List<ItemModel> itemModelList = itemService.listItem();
        //使用stream api将list内的itemModel转化为ItemVO;
        List<ItemVO> itemVOList = itemModelList.stream().map(itemModel -> {
            ItemVO itemVO = this.convertFromItemModel(itemModel);
            return itemVO;
        }).collect(Collectors.toList());
        return CommonReturnType.create(itemVOList);
    }

    public ItemVO convertFromItemModel(ItemModel itemModel) {
        if (itemModel == null)
            return null;
        ItemVO itemVO = new ItemVO();
        BeanUtils.copyProperties(itemModel, itemVO);
        if(itemModel.getPromoModel() != null){
            //有正在进行或即将进行的秒杀活动
            itemVO.setPromoStatus(itemModel.getPromoModel().getStatus());
            itemVO.setPromoId(itemModel.getPromoModel().getId());
            itemVO.setStartDate(itemModel.getPromoModel().getStartDate().toString(DateTimeFormat.forPattern("yyyy--MM--dd HH:mm:ss")));
            itemVO.setPromoPrice(itemModel.getPromoModel().getPromoItemPrice());
        }else{
            itemVO.setPromoStatus(0);
        }
        return itemVO;
    }
}
